/*->c.vtsend */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"


#include "h.def"
#include "h.wos"
#include "h.main"
#include "h.ram"
#include "h.mym"
#include "h.key"

#include "h.serial"
#include "h.dir"

#include "h.term"
#include "h.xext"


#include "h.vtdef"
#include "h.vtchar"
#include "h.vtact"
#include "h.vtsend"


/***************************************************************************/
/*
  Code to handle VT sending strings
*/
/***************************************************************************/



/* used to send bytes to line by VT terminal */

void vtlinelo(int i)
{
 if(localmode)
 {
  if(!vtselect)
  {
   savetmode(TMODEVT);
   tty(i);
   loadtmode();
  }
 }
 else
 {
  if(echomode) tty(i);
  termoutbyte(i);
 }
}



int vtline(int ch)
{
 static int pending;

 if(vt220 && c1codes)
 {
  if(pending)
  {
   if(ch>='@' && ch<='_') vtlinelo(ch+0x80-'@');
   else
   {
    vtlinelo(ESC);
    vtlinelo(ch);
   }
   pending=0;
  }
  else
  if(ch==ESC)
  {
   pending=1;
  }
  else vtlinelo(ch);
 }
 else vtlinelo(ch);

 return(0);
}



/* used to send key codes to line */

void vtkeyline(int i)
{
 vtline(i);
}



/* send string to line */

void vtstringline(char * string)
{
 int len=strlen(string);
 int i;
 for(i=0;i<len;i++) if(vtline(string[i])) break;
}



/* convert | seqs return 0 on failure */

int vtconvertstringline(char * string)
{
 return(expandmacro(vtline,string));
}




/*****************************************************************************/

/* Request CSI c -- Terminal ident */

/*  Response -> ESC [ ?1; options c  VT100  */
/*           -> ESC [ ?6; options c  VT102  */
/*           -> ESC [ ?63;1;2;8;9 c  VT320  */
/*           -> ESC [ ?62;2c         VT220  */


char vt220ident[32]="|[[?63;1;2;8;9c";
char vt102ident[32]="|[[?6;2c";
char vt52ident[32] ="|[/Z";

void sendatt(void)
{
 if(!ansimode) vtconvertstringline(vt52ident);
 if(vt220)     vtconvertstringline(vt220ident);
 else          vtconvertstringline(vt102ident);
}


void sendidentify(void)
{
 vtconvertstringline(vt52ident);
}


void setvtident(int fp)
{
 int    term=stack[fp];
 char * ident=stringptr(stack[fp+1]);

 if(term==TERMVT220) strcpy(vt220ident,ident);
 else
 if(term==TERMVT100) strcpy(vt102ident,ident);
 else
 if(term==TERMVT52)  strcpy(vt52ident,ident);
}


/*****************************************************************************/

/* Request CSI > c -- Secondary devioce attributes */

/* Response -> ESC [ >1;17;0c    VT220 */
/*             ESC [ >24;0;0;0c  VT320 */

/* send VT220 device attributes */

char vt220attribs[32]="|[[>24;0;0;0c";


void sendatt220(void)
{
 vtconvertstringline(vt220attribs);
}


void setvtdevatt(int fp)
{
 char * p=stringptr(stack[fp]);
 strcpy(vt220attribs,p);
}


/****************************************************************************/

/* Request CSI 5 n -- operating status */

/* ESC [ 0 n OK */
/* ESC [ 3 n not OK */

void sendstatusok(void)
{
 vtconvertstringline("|[[0n");
}


/*****************************************************************************/

/* Request CSI 6 n -- cursor posn */


/* ESC [ x;y R      */

void sendcursorposn(void)
{
 int  i;
 char string[64];

 if(originmode) i=ttyy-scltop+1;
 else           i=ttyy+1;

 if(i<0) i=0;
 sprintf(string,"|[[%d;%dR",i,ttyx+1);
 vtconvertstringline(string);
}


/*****************************************************************************/

/* Request CSI ? 15 n -- printer status */

/* ESC [ ? 10 n  ready */
/* ESC [ ? 11 n not ready */
/* ESC [ ? 13 n no printer */

void sendprintstatus(void)
{
 vtconvertstringline("|[[?1");
 if(printer) vtline('0');
 else        vtline('3');
 vtline('n');
}


/****************************************************************************/

/* Request CSI ? 25 n -- User definable keys lock status */


void sendlockstatus(void)
{
 if(flock) vtconvertstringline("|[[?21n");
 else      vtconvertstringline("|[[?20n");
}


/*****************************************************************************/

/* Request CSI ? 26 n -- Keyboard dialect */

/* Response CSI ? 27; Ps n           */
/* Ps==1 ASCII 2,British, 8,Dutch... */ 

void sendkbdialect(void)
{
 char string[32];
 sprintf(string,"|[[?27;%dn",vtcsetmap[vtncs].keyident);
 vtconvertstringline(string);
}


/*****************************************************************************/

/* Request CSI 1 $ u -- upload terminal state */

/* Response DCS 1 $ ST */

void sendterminalstate(void)
{
 vtconvertstringline("|[P1$|[\\");
}

/*****************************************************************************/

/* Request    CSI & u -- request upss */
/* Response   DCS Ps !u string ST     */
/* Ps==0 for 94 byte cset 1 for 96    */
/* string is ident A or %5            */

void vtsendupss(void)
{
 char string[32];
 sprintf(string,"|[P%d!u%s|[\\",vtcsetmap[vtupss].size==96,
                                vtcsetmap[vtupss].ident);
 vtconvertstringline(string);
}

/*****************************************************************************/

/* Request   CSI 1 $ w -- cursor information report */
/* Response  DCS 1 $ u Pr;Pc;Pp;Srend;Satt;Sflag;Pgl;Pgr;Scss;Sdesig ST */
/* Pr==row
   Pc==columns
   Pp=1
   Srend=0x40+8(rev video on)+4(blink)+2(underline)+1(bold)
   Satt =0x40+(selective erase)
   Sflag=0x40+8(auto wrap pending)+4(SS3 pending)+2(SS2 pending)+
   Scss=0x40+8*(G3==96)+4*(G2==96)+2*(G1==96)+1*(G0==96)
   Sdesig string of idents for G0-G3
 */

void vtsendcursorinforeport(void)
{
 char string[64];
 int  Pr;
 int  Pc;
 int  Srend;
 int  Satt;
 int  Sflag;
 int  Pgl;
 int  Pgr;
 int  Scss;
 char Sdesig[32];
 int  i;

 Pr=ttyy+1;
 Pc=ttyx+1;
 Srend=0x40+8*((rendition & 0x40)!=0)+4*((rendition & 0x10)!=0)+
            2*((rendition &  0x8)!=0)+1*((rendition &  0x1)!=0);
 Satt=0x40+selerase;
 Sflag=0x40+8*pend+4*vtssg3+2*vtssg2;
 Pgl=vtgl;
 Pgr=vtgr;

 for(Scss=0x40,i=0;i<4;i++) Scss|=(vtcsetmap[vtgn[i]].size==96)<<i;

 sprintf(Sdesig,"%s%s%s%s",vtcsetmap[vtgn[0]].ident,
  vtcsetmap[vtgn[1]].ident,vtcsetmap[vtgn[2]].ident,vtcsetmap[vtgn[3]].ident);

 sprintf(string,"|[P1$u%d;%d;1;%d;%d;%d;%d;%d;%d;%s|[\\",
                              Pr,Pc,Srend,Satt,Sflag,Pgl,Pgr,Scss,Sdesig);
 vtconvertstringline(string);
}


/*****************************************************************************/


/* Request   CSI 2 $ w -- tab stop report */
/* Response  DCS 2 $ u Pc; Pc; ST         */
/* posns number from 1                    */

void vtsendtabs(void)
{
 int i;
 char string[32];

 vtconvertstringline("|[P2$u");

 for(i=0;i<width;i++)
  if(tabs[i]) 
  {
   sprintf(string,"%d;",i+1);
   vtconvertstringline(string);
  }
 vtconvertstringline("|[\\");
}


/*****************************************************************************/

/* Request   CSI Pa $ p     */
/* Response  CSI Pa; Ps $ y */
/* Ps 0==unknown mode 1==set 2==reset 3==permanently set 4==perm. reset  */
/* Pa 2==keyboard locked 3==debug 4==insert 10==horizontal editing       */
/*   12==local echo  20==newline */

void vtreportansimode(int n)
{
 int flag=0;
 char string[32];

 switch(n)
 {
  case  2:
          flag=1+keylockmode;
          break;

  case  3:
          flag=1+(concode==TERMDISPCTRLS);
          break;

  case  4:
          flag=1+insertmode;
          break;

  case 10:
          flag=4;
          break;

  case 12:
          flag=1+echomode;
          break;

  case 20:
          flag=1+newlinemode;
          break;
 }

 sprintf(string,"|[[%d;%d$y",n,flag);
 vtconvertstringline(string);
}


/*****************************************************************************/
/* Request  CSI ? Pd $ p  */
/* Response CSI Pa;Ps $ y */


void vtreportdecmode(int n)
{
 int flag=0;
 char string[32];

 switch(n)
 {
  case  1:                     /* cursor key mode */
          flag=1+cursorkeymode;
          break;

  case  2:                     /* ansi mode */
          flag=1+ansimode;
          break;

  case  3:                     /* column == 132 */
          flag=1+(width==132);
          break;

  case  4:                     /* smooth scroll */
          flag=1+smooth;
          break;

  case  5:                     /* reverse video */
          flag=1+screenmode;
          break;

  case  6:
          flag=1+originmode;
          break;

  case  7:
          flag=1+wrapmode;
          break;

  case  8:
          flag=1+automode;
          break;

  case 18:
          flag=1+printff;
          break;

  case 19:
          flag=1+printarea;
          break;

  case 25:
          flag=1+vtcurs;
          break;

  case 42:
          flag=1+vtncsinuse;
          break;

  case 66:
          flag=1+(keypadmode==0);
          break;

  case 67:                         /* backarrow sends BS */
          flag=2;
          break;

  case 68:                         /* keyboard usage */
          flag=2;
          break;
 }

 sprintf(string,"|[[%d;%d$y",n,flag);
 vtconvertstringline(string);
}

/*****************************************************************************/

/* CSI sol x Request terminal parameters VT102 only */
/* Response CSI sol; par; nbits; xspeed; rspeed; clkmul; flags x */


static char * vtrates[MAXRATES]={"8","32","48","64","88","104",
             "112","120","0","16","24","56","72","96","96","96","96","96"};
     


/*
   parity=0 none  1
   parity=1 even  5
   parity=2 odd   4
   parity=3 mark  3
   parity=4 space 2
*/



void sendterminalparams(void)
{
 vtconvertstringline("|[[3;");
 vtline("15432"[paritybits]);  /* parity  */
 vtline(';');
 vtline("21"[databits-7]);       /* nbits */
 vtline(';');
 vtstringline(vtrates[bitrate2int(txbitrate)]); /* txspeed */
 vtline(';');
 vtstringline(vtrates[bitrate2int(rxbitrate)]); /* rxspeed */
 vtstringline(";1;0x");
}


/*****************************************************************************/

/* Request  ENQ        */
/* Response Answerback */


void answerback(void)
{
 vtconvertstringline(vtanswerback);
}

/*****************************************************************************/

void vthold(void)
{
 vtline(XOFF);
}


void vtrelease(void)
{
 vtline(XON);
}

